package com.sos.config 
{
	
	import com.sos.core.DataObject;
	import com.sos.core.game.GameOptions;
	import com.sos.data.adapters.ConfigurationAdapter;
	import com.sos.logging.Dumper;
	import com.sos.logging.IDumpable;
	import com.sos.logging.LogOptions;
	
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import com.sos.DebugOptions;

	/**
	 * ToccerTCG application configuration 
	 * @author luca tavecchia
	 * 
	 */	
	public class Configuration extends DataObject implements IDumpable
	{
		
		// -------------------------------------------------------------------------------
		// CONSTANTS
		// -------------------------------------------------------------------------------
		
		// JSON Property names
		protected const		JSON_PROPERTY_SERVER_URL:String				= "serverUrl";
		protected const		JSON_PROPERTY_CALLS_URL:String				= "callsUrl";
		protected const		JSON_PROPERTY_IMAGES_URL:String				= "imagesUrl";
		protected const		JSON_PROPERTY_GAME_OPTIONS:String			= "gameOptions";
		protected const		JSON_PROPERTY_LOG_OPTIONS:String			= "logOptions";
		protected const		JSON_PROPERTY_DEBUG_OPTIONS:String			= "debugOptions";
		
		// Default values
		protected const		DEFAULT_SERVER_URL:String					= "http://striptemple.com/sostcg/";
		protected const		DEFAULT_CALL_URL:String						= "http://striptemple.com/sostcg/ClientComm/Flash/";
		protected const		DEFAULT_IMAGES_URL:String					= "http://striptemple.com/sostcg/ClientComm/Images/";
		protected const		DEFAULT_OLD_ACTION_CARD_PARSING:Boolean		= false;
		protected const		DEFAULT_OLD_USER_LOGIN_HANDLING:Boolean		= false;
		
		// -------------------------------------------------------------------------------
		// FIELDS
		// -------------------------------------------------------------------------------
		
		// URLs
		private var _serverUrl:String;
		private var _callsUrl:String;
		private var _imagesUrl:String;
		// Retrocompatibility
		private var	_useOldActionCardParsing:Boolean;
		private var	_useOldUserLoginHandling:Boolean;
		// Options
		private var _logOptions:LogOptions;
		private var _debugOptions:DebugOptions;
		private var _gameOptions:GameOptions;
		
		// -------------------------------------------------------------------------------
		// CONSTRUCTOR
		// -------------------------------------------------------------------------------
		
		public function Configuration(data:Object = null)
		{
			// Init objects
			_logOptions = new LogOptions();
			_debugOptions= new DebugOptions();
			_gameOptions = new GameOptions();
			// Init
			clear();
			// If data is provided, initializes the instance
			if (data != null) load(data);
		}
		
		// -------------------------------------------------------------------------------
		// PROPERTIES
		// -------------------------------------------------------------------------------

		public function get serverUrl():String
		{
			return _serverUrl;
		}
		
		public function set serverUrl(value:String):void
		{
			_serverUrl = value;
		}
		
		public function get callsUrl():String
		{
			return _callsUrl;
		}
		
		public function set callsUrl(value:String):void
		{
			_callsUrl = value;
		}
		
		public function get imagesUrl():String
		{
			return _imagesUrl;
		}
		
		public function set imagesUrl(value:String):void
		{
			_imagesUrl = value;
		}
		
		public function get useOldActionCardParsing():Boolean
		{
			return _useOldActionCardParsing;
		}
		
		public function set useOldActionCardParsing(value:Boolean):void
		{
			_useOldActionCardParsing = value;
		}
		
		public function get useOldUserLoginHandling():Boolean
		{
			return _useOldUserLoginHandling;
		}
		
		public function set useOldUserLoginHandling(value:Boolean):void
		{
			_useOldUserLoginHandling = value;
		}

		public function get logOptions():LogOptions
		{
			return _logOptions;
		}
		
		public function set logOptions(value:LogOptions):void
		{
			_logOptions = value;
		}
		
		public function get debugOptions():DebugOptions
		{
			return _debugOptions;
		}
		
		public function set debugOptions(value:DebugOptions):void
		{
			_debugOptions = value;
		}
		
		public function get gameOptions():GameOptions
		{
			return _gameOptions;
		}
		
		public function set gameOptions(value:GameOptions):void
		{
			_gameOptions = value;
		}
				
		// -------------------------------------------------------------------------------
		// PRIVATE METHODS
		// -------------------------------------------------------------------------------
		
		// DataObject implementation
				
		/**
		 * 
		 * @param data
		 */		
		override protected function fill(data:Object):void
		{
			// Data loading
			if (data.hasOwnProperty(JSON_PROPERTY_SERVER_URL))	_serverUrl = data[JSON_PROPERTY_SERVER_URL];
			if (data.hasOwnProperty(JSON_PROPERTY_CALLS_URL))	_callsUrl = data[JSON_PROPERTY_CALLS_URL];
			if (data.hasOwnProperty(JSON_PROPERTY_IMAGES_URL)) 	_imagesUrl = data[JSON_PROPERTY_IMAGES_URL];
			// Options loading
			if (data.hasOwnProperty(JSON_PROPERTY_LOG_OPTIONS)) 	_logOptions.load(data[JSON_PROPERTY_LOG_OPTIONS]);
			if (data.hasOwnProperty(JSON_PROPERTY_GAME_OPTIONS))	_gameOptions.load(data[JSON_PROPERTY_GAME_OPTIONS]);
			if (data.hasOwnProperty(JSON_PROPERTY_DEBUG_OPTIONS)) 	_debugOptions.load(data[JSON_PROPERTY_DEBUG_OPTIONS]);
		}

		
		// -------------------------------------------------------------------------------
		// PUBLIC METHODS
		// -------------------------------------------------------------------------------
		
		public function equals(configuration:Configuration):Boolean
		{	
			return	_serverUrl == configuration.serverUrl &&
					_logOptions.equals(configuration.logOptions) &&
					_debugOptions.equals(configuration.debugOptions) &&
					_gameOptions.equals(configuration.gameOptions);
		}
		
		override public function clear():void
		{
			_serverUrl 					= DEFAULT_SERVER_URL;
			_callsUrl					= DEFAULT_CALL_URL;
			_imagesUrl					= DEFAULT_IMAGES_URL;
			_useOldActionCardParsing 	= DEFAULT_OLD_ACTION_CARD_PARSING;
			_useOldActionCardParsing 	= DEFAULT_OLD_USER_LOGIN_HANDLING;
			_logOptions.clear();
			_debugOptions.clear();
			_gameOptions.clear();
		}
		
		public function dump(source:Array = null, indentDepth:int = 0):Array
		{
			return Dumper.dump(this, null, source, indentDepth);
		}
		
		
		// -------------------------------------------------------------------------------
		// STATIC METHODS
		// -------------------------------------------------------------------------------
		
		private static var _loaderCallback:Function;
		
		// UrlLoader callback
		
		protected static function loaderComplete(event:Event):void
		{
			// Safe exec
			try
			{
				// retrieve the url loader
				var loader:URLLoader = event.target as URLLoader;
				// create the configuration using the adaper
				var config:Configuration = ConfigurationAdapter.fromXML(new XML(loader.data));
				// Execute the callback passing the loaded configuration
				_loaderCallback(config);
			}
			// Unexpected exception
			catch (exc:Error)
			{
				throw new Error("Configuration.load() unexpected error: " + exc.toString());
			}
		}
		
		protected static function loaderIOError(e:IOErrorEvent):void
		{
			throw new Error("Configuration.load() IO error: " + e.text);
		}
		
		protected static function loaderSecurityError(e:SecurityErrorEvent):void
		{
			throw new Error("Configuration.load() security error: " + e.text);
		}
		
		
		/**
		 * Loads the configuration from an xml file at the provided URL. If 
		 * @param url
		 * @param callback
		 */		
		public static function load(url:String, callback:Function):void
		{
			// Safe execution
			try
			{
				// Save a reference of the callback
				_loaderCallback = callback;
				// Creates the loader
				var loader:URLLoader = new URLLoader();
				loader.addEventListener(Event.COMPLETE, loaderComplete);
				loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, loaderSecurityError);
				loader.addEventListener(IOErrorEvent.IO_ERROR, loaderIOError);
			} 
			catch(e:Error) 
			{
				trace("Configuration.load(" + url + ") failed: " + e.toString());
			}
		}
		
		/**
		 * Returns a new instance of the default configuration 
		 * @return Default Configuration object
		 */		
		public static function getDefault():Configuration
		{
			// Creates and popolates the default configuration
			var cfg:Configuration = new Configuration();
			cfg.logOptions 	 = LogOptions.DEFAULT;
			cfg.debugOptions = DebugOptions.DEFAULT;
			return cfg;
		}
	
	}
}